/**
 * 集合(Set)模块使用示例 (zh-set.js)
 * 演示中文命名集合的各种操作和集合论概念实现
 */

// 支持 CommonJS 和 ES 模块导入
const setModule = require('../../zh/公共函数/zh-set.js');
const {
  集合
} = setModule || {
  集合: setModule.集合 || setModule.default
};

console.log('=== 集合(Set)模块 (zh-set.js) 使用示例 ===\n');

// ===== 1. 基本集合操作 =====
console.log('1. 基本集合操作:');

// 1.1 创建空集合
const 空集合 = new 集合();
console.log('创建空集合:');
console.log('  集合大小:', 空集合.大小());
console.log('  集合内容:', 空集合.转数组());

// 1.2 创建带初始值的集合
const 数字集合 = new 集合([1, 2, 3, 4, 5]);
console.log('\n创建带初始值的集合:');
console.log('  集合大小:', 数字集合.大小());
console.log('  集合内容:', 数字集合.转数组());

// 1.3 添加元素
const 添加后集合 = 数字集合.添加(6, 7);
console.log('\n添加元素后:');
console.log('  原集合大小:', 数字集合.大小());
console.log('  新集合大小:', 添加后集合.大小());
console.log('  新集合内容:', 添加后集合.转数组());

// 1.4 添加重复元素（不会改变集合）
const 添加重复集合 = 添加后集合.添加(5, 6);
console.log('\n添加重复元素后:');
console.log('  集合大小:', 添加重复集合.大小());
console.log('  集合内容:', 添加重复集合.转数组());

// 1.5 删除元素
const 删除后集合 = 添加重复集合.删除(3);
console.log('\n删除元素后:');
console.log('  原集合大小:', 添加重复集合.大小());
console.log('  新集合大小:', 删除后集合.大小());
console.log('  新集合内容:', 删除后集合.转数组());

// 1.6 检查元素是否存在
console.log('\n检查元素存在:');
console.log('  是否包含2:', 删除后集合.包含(2));
console.log('  是否包含3:', 删除后集合.包含(3));

// 1.7 清空集合
const 清空后集合 = 删除后集合.清空();
console.log('\n清空集合后:');
console.log('  原集合大小:', 删除后集合.大小());
console.log('  新集合大小:', 清空后集合.大小());

// ===== 2. 集合转换操作 =====
console.log('\n2. 集合转换操作:');

const 转换集合 = new 集合(['a', 'b', 'c', 'd']);

// 2.1 转数组
console.log('转数组:');
const 数组结果 = 转换集合.转数组();
console.log('  结果类型:', Array.isArray(数组结果) ? '数组' : typeof 数组结果);
console.log('  结果内容:', 数组结果);

// 2.2 转字符串
console.log('\n转字符串:');
const 字符串结果 = 转换集合.转字符串();
console.log('  结果类型:', typeof 字符串结果);
console.log('  结果内容:', 字符串结果);

// 2.3 获取原始Set
console.log('\n获取原始Set:');
const 原始Set = 转换集合.取值();
console.log('  结果类型:', Object.prototype.toString.call(原始Set));
console.log('  是否为Set实例:', 集合.是否集合(原始Set));

// ===== 3. 集合论操作 =====
console.log('\n3. 集合论操作:');

// 创建测试集合
const 集合A = new 集合([1, 2, 3, 4, 5]);
const 集合B = new 集合([4, 5, 6, 7, 8]);
const 集合C = new 集合([3, 6, 9]);
const 原生Set = new Set([7, 8, 9, 10]);

console.log('  集合A:', 集合A.转数组());
console.log('  集合B:', 集合B.转数组());
console.log('  集合C:', 集合C.转数组());
console.log('  原生Set:', 原生Set);

// 3.1 并集
const 并集结果 = 集合A.并集(集合B);
console.log('\n并集 A ∪ B:');
console.log('  结果:', 并集结果.转数组());

// 3.2 多集合并集
const 多并集结果 = 集合A.并集(集合B, 集合C);
console.log('\n多集合并集 A ∪ B ∪ C:');
console.log('  结果:', 多并集结果.转数组());

// 3.3 与原生Set的并集
const 与原生Set并集 = 集合A.并集(原生Set);
console.log('\n与原生Set的并集 A ∪ Set:');
console.log('  结果:', 与原生Set并集.转数组());

// 3.4 交集
const 交集结果 = 集合A.交集(集合B);
console.log('\n交集 A ∩ B:');
console.log('  结果:', 交集结果.转数组());

// 3.5 多集交集
const 多交集结果 = 集合A.交集(集合B, 并集结果);
console.log('\n多集交集 A ∩ B ∩ (A∪B):');
console.log('  结果:', 多交集结果.转数组());

// 3.6 差集
const 差集结果 = 集合A.差集(集合B);
console.log('\n差集 A - B:');
console.log('  结果:', 差集结果.转数组());

// 3.7 多集差集
const 多差集结果 = 集合A.差集(集合B, 集合C);
console.log('\n多集差集 A - B - C:');
console.log('  结果:', 多差集结果.转数组());

// 3.8 补集
const 补集结果 = 集合A.补集(集合B);
console.log('\n补集 (A ∪ B) - (A ∩ B):');
console.log('  结果:', 补集结果.转数组());

// ===== 4. 遍历操作 =====
console.log('\n4. 遍历操作:');

const 遍历集合 = new 集合(['红', '绿', '蓝', '黄']);

// 4.1 使用遍历方法
console.log('遍历所有元素:');
遍历集合.遍历((元素, 相同元素, 集合) => {
  console.log(`  元素: ${元素}`);
});

// 4.2 链式调用中的遍历
console.log('\n链式调用中的遍历:');
遍历集合
  .添加('紫')
  .遍历((元素) => {
    console.log(`  链式调用中的元素: ${元素}`);
  });

// 4.3 打印集合
console.log('\n打印集合内容:');
遍历集合.打印();

// ===== 5. 复杂元素类型 =====
console.log('\n5. 复杂元素类型:');

// 5.1 对象作为元素
const 对象1 = { id: 1, 名称: '对象1' };
const 对象2 = { id: 2, 名称: '对象2' };
const 对象3 = { id: 3, 名称: '对象3' };

const 对象集合 = new 集合([对象1, 对象2]);
const 添加对象后集合 = 对象集合.添加(对象3);

console.log('对象集合:');
添加对象后集合.遍历((元素) => {
  console.log(`  对象ID: ${元素.id}, 名称: ${元素.名称}`);
});

// 注意：Set是按引用相等性比较对象的
const 相同内容对象 = { id: 1, 名称: '对象1' };
console.log('\n添加相同内容但不同引用的对象:');
console.log('  原对象是否已包含:', 对象集合.包含(相同内容对象));
const 添加后是否不同 = 对象集合.添加(相同内容对象).大小() !== 对象集合.大小();
console.log('  添加后是否增加元素:', 添加后是否不同);

// 5.2 数组作为元素
const 数组元素1 = [1, 2];
const 数组元素2 = [3, 4];
const 数组集合 = new 集合([数组元素1]);

console.log('\n数组集合:');
数组集合
  .添加(数组元素2)
  .遍历((元素) => {
    console.log(`  数组元素: [${元素.join(', ')}]`);
  });

// ===== 6. 静态方法 =====
console.log('\n6. 静态方法:');

// 6.1 创建集合
const 静态创建集合 = 集合.创建(['x', 'y', 'z']);
console.log('静态方法创建集合:');
console.log('  集合大小:', 静态创建集合.大小());
console.log('  集合内容:', 静态创建集合.转数组());

// 6.2 检查是否为Set实例
const 测试Set = new Set();
const 测试对象 = { a: 1 };

console.log('\n检查实例类型:');
console.log('  测试Set是否为Set实例:', 集合.是否集合(测试Set));
console.log('  测试对象是否为Set实例:', 集合.是否集合(测试对象));
console.log('  集合类实例是否为Set实例:', 集合.是否集合(静态创建集合.取值()));

// ===== 7. 链式调用 =====
console.log('\n7. 链式调用:');

// 7.1 基本链式调用
const 链式集合 = new 集合([1, 2])
  .添加(3, 4)
  .添加(5);

console.log('基本链式调用:');
console.log('  结果集合:', 链式集合.转数组());

// 7.2 复杂链式调用（包含集合论操作）
const 复杂链式结果 = 集合.创建([1, 2, 3])
  .添加(4, 5)
  .并集(new 集合([4, 5, 6, 7]))
  .差集(new 集合([2, 4, 6]));

console.log('\n复杂链式调用 (创建+添加+并集+差集):');
console.log('  结果集合:', 复杂链式结果.转数组());

// 7.3 链式调用后遍历
console.log('\n链式调用后遍历:');
集合.创建(['a', 'b', 'c'])
  .添加('d')
  .遍历((元素) => {
    console.log(`  元素: ${元素}`);
  });

// ===== 8. 实际应用场景 =====
console.log('\n8. 实际应用场景:');

// 8.1 数组去重
console.log('\n8.1 数组去重:');
const 重复数组 = [1, 2, 2, 3, 4, 4, 5, 5, 5];
const 去重结果 = new 集合(重复数组).转数组();

console.log('  原始数组:', 重复数组);
console.log('  去重结果:', 去重结果);

// 8.2 用户权限管理
console.log('\n8.2 用户权限管理:');
const 权限系统 = {
  // 定义角色权限
  角色权限: {
    游客: new 集合(['查看', '浏览']),
    用户: new 集合(['查看', '浏览', '评论', '收藏']),
    管理员: new 集合(['查看', '浏览', '评论', '收藏', '编辑', '删除'])
  },
  
  // 获取用户权限（多个角色权限的并集）
  获取用户权限(角色列表) {
    let 总权限 = new 集合();
    for (const 角色 of 角色列表) {
      if (this.角色权限[角色]) {
        总权限 = 总权限.并集(this.角色权限[角色]);
      }
    }
    return 总权限;
  },
  
  // 检查用户是否有特定权限
  检查权限(用户权限, 目标权限) {
    return 用户权限.包含(目标权限);
  },
  
  // 获取用户缺失的权限
  获取缺失权限(用户权限, 所需权限列表) {
    const 所需权限 = new 集合(所需权限列表);
    return 所需权限.差集(用户权限);
  }
};

// 测试权限管理
const 用户角色 = ['用户'];
const 用户权限 = 权限系统.获取用户权限(用户角色);

console.log('  用户角色:', 用户角色);
console.log('  用户拥有的权限:', 用户权限.转数组());
console.log('  是否可以编辑:', 权限系统.检查权限(用户权限, '编辑'));
console.log('  是否可以评论:', 权限系统.检查权限(用户权限, '评论'));
console.log('  缺失的管理员权限:', 权限系统.获取缺失权限(
  用户权限, ['编辑', '删除', '管理']
).转数组());

// 8.3 数据分析应用（找出共同元素）
console.log('\n8.3 数据分析应用 (找出共同元素):');
const 数据分析 = {
  // 找出多个数组中的共同元素
  找出共同元素(...数组列表) {
    if (数组列表.length === 0) return new 集合();
    
    // 从第一个数组创建集合
    let 共同元素 = new 集合(数组列表[0]);
    
    // 依次与其他数组计算交集
    for (let i = 1; i < 数组列表.length; i++) {
      共同元素 = 共同元素.交集(new 集合(数组列表[i]));
      // 如果已经没有共同元素，可以提前结束
      if (共同元素.大小() === 0) break;
    }
    
    return 共同元素;
  },
  
  // 分析用户标签重叠度
  分析标签重叠度(用户1标签, 用户2标签) {
    const 标签1集合 = new 集合(用户1标签);
    const 标签2集合 = new 集合(用户2标签);
    
    const 共同标签 = 标签1集合.交集(标签2集合);
    const 总不同标签 = 标签1集合.并集(标签2集合);
    
    return {
      共同标签: 共同标签.转数组(),
      重叠度: 总不同标签.大小() > 0 ? 共同标签.大小() / 总不同标签.大小() : 0
    };
  }
};

// 测试共同元素查找
const 数组1 = [1, 2, 3, 4, 5];
const 数组2 = [3, 4, 5, 6, 7];
const 数组3 = [5, 6, 7, 8, 9];

console.log('  共同元素测试:');
console.log('    数组1:', 数组1);
console.log('    数组2:', 数组2);
console.log('    数组3:', 数组3);
console.log('    三个数组的共同元素:', 数据分析.找出共同元素(数组1, 数组2, 数组3).转数组());
console.log('    数组1和数组2的共同元素:', 数据分析.找出共同元素(数组1, 数组2).转数组());

// 测试标签重叠度分析
const 用户1标签 = ['JavaScript', 'React', 'Node.js', 'Vue', 'HTML'];
const 用户2标签 = ['React', 'Node.js', 'Python', 'Java', 'TypeScript'];

const 重叠分析结果 = 数据分析.分析标签重叠度(用户1标签, 用户2标签);
console.log('\n  用户标签重叠分析:');
console.log('    用户1标签:', 用户1标签);
console.log('    用户2标签:', 用户2标签);
console.log('    共同标签:', 重叠分析结果.共同标签);
console.log('    重叠度:', (重叠分析结果.重叠度 * 100).toFixed(2) + '%');

// 8.4 文本处理应用
console.log('\n8.4 文本处理应用:');
const 文本工具 = {
  // 提取文本中不重复的单词
  提取不重复单词(文本) {
    // 简单分词（实际应用可能需要更复杂的分词逻辑）
    const 单词 = 文本.toLowerCase()
      .replace(/[^\w\s]/g, '') // 移除标点符号
      .split(/\s+/);
    
    return new 集合(单词);
  },
  
  // 计算两个文本的词汇相似度
  计算词汇相似度(文本1, 文本2) {
    const 单词集1 = this.提取不重复单词(文本1);
    const 单词集2 = this.提取不重复单词(文本2);
    
    const 共同单词 = 单词集1.交集(单词集2);
    const 所有单词 = 单词集1.并集(单词集2);
    
    // Jaccard相似度 = 交集大小 / 并集大小
    return 所有单词.大小() > 0 ? 共同单词.大小() / 所有单词.大小() : 0;
  }
};

// 测试文本处理
const 文本1 = 'JavaScript是一种流行的编程语言，用于Web开发。';
const 文本2 = 'Python也是一种流行的编程语言，广泛用于数据科学和Web开发。';

const 不重复单词1 = 文本工具.提取不重复单词(文本1);
const 不重复单词2 = 文本工具.提取不重复单词(文本2);
const 相似度 = 文本工具.计算词汇相似度(文本1, 文本2);

console.log('  文本1不重复单词数量:', 不重复单词1.大小());
console.log('  文本2不重复单词数量:', 不重复单词2.大小());
console.log('  文本共同单词:', 不重复单词1.交集(不重复单词2).转数组());
console.log('  文本词汇相似度:', (相似度 * 100).toFixed(2) + '%');

console.log('\n=== 所有集合示例执行完成 ===');
